﻿using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using IGM.DataProvider;
using IGM.Framework.Constants;

namespace IGM.Business
{
    public partial class Business
    {
        #region -- Get Student --

        public List<Student> GetListStudent()
        {
            return DataContex.Students.ToList();
        }

        /// <summary>
        /// This function shows list of Student.
        /// </summary>
        /// <returns></returns>
        public List<Student> GetListStudentByMajorId(int majorId)
        {
            return DataContex != null && majorId > 0
                        ? DataContex.Students.Where(m => m.IdMajor == majorId).ToList() : null;
        }

        public List<Student> GetStudentQualityGraduation(int majorId, int kindmarkId, double condition)
        {
            var query = (DataContex.Students.Where(m => m.IdMajor == majorId).Select(orders => orders));

            var query1 = (DataContex.StudentMarks.Where(m => m.IdKindMark == kindmarkId && m.Mark >= condition).Select(
                orders => orders));

            var matches = (query1.SelectMany(a => query, (a, b) => new { a, b }).Where(@t => @t.a.IdStudent == @t.b.Id).
                Select(@t => @t.b));

            return matches.ToList();
        }
      
        public int GetStudentId(string studentCode)
        {
            return string.IsNullOrEmpty(studentCode) ? 0
                       : DataContex.Students.FirstOrDefault(s => s.Code.ToLower() == studentCode.ToLower()).Id;
        }

        #endregion

        #region Common

        private static bool StudentCommonValidator(Student student, out string message)
        {
            if (string.IsNullOrWhiteSpace(student.Name))
            {
                message = string.Format(ConstantMessages.RequireFieldIsBlank, "tên Sinh viên");
                return false;
            }

            if (string.IsNullOrWhiteSpace(student.Code))
            {
                message = string.Format(ConstantMessages.RequireFieldIsBlank, "mã Sinh viên");
                return false;
            }

            if (student.Name.Length >= 50)
            {
                message = string.Format(ConstantMessages.FieldDataOverMaxLength, "tên Sinh viên", 50);
                return false;
            }

            if (student.Code.Length > 8)
            {
                message = string.Format(ConstantMessages.FieldDataOverMaxLength, "mã Sinh viên", 8);
                return false;
            }

            message = string.Empty;
            return true;
        }

        #endregion

        #region -- Add Student --

        /// <summary>
        /// 
        /// </summary>
        /// <param name="student"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public bool AddStudentValidator(Student student, out string message)
        {
            if (!StudentCommonValidator(student, out message)) return false;

            if (DataContex.Students.Any(f => f.Code.ToLower() == student.Code.ToLower()))
            {
                message = string.Format(ConstantMessages.ItemIsExisted, student.Code);
                return false;
            }

            return true;
        }

        /// <summary>
        /// This function add a new facutly into list.
        /// </summary>
        public void AddStudent(Student student)
        {
            DataContex.Students.AddObject(student);
            DataContex.SaveChanges();
        }

        #endregion

        #region -- Edit Major --


        public bool EditStudentValidator(Student student, out string message)
        {
            var id = student.Id;

            if (!StudentCommonValidator(student, out message)) return false;

            if (DataContex.Students.Any(m => m.Code.ToLower() == student.Code.ToLower() && m.Id != id))
            {
                message = string.Format(ConstantMessages.ItemIsExisted, student.Code);
                return false;
            }
          
            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="student"></param>
        /// <returns></returns>
        public bool EditStudent(Student student)
        {
            var id = student.Id;
            var updateStudent = DataContex.Students.SingleOrDefault(f => f.Id == id);

            if (updateStudent == null)
                return false;

            updateStudent.Name = student.Name;
            updateStudent.Code = student.Code;
            updateStudent.DateOfBirth = student.DateOfBirth;
            updateStudent.Term = student.Term;

            DataContex.SaveChanges();
            return true;
        }

        #endregion

        #region -- Delete Student --

        public bool DeleteStudentsValidator(IEnumerable<Student> students, out string message)
        {
            const string intialize = "Sinh viên: ";
            var itemsCannotIdentify = (from student in students
                                       let id = student.Id
                                       where !DataContex.Students.Any(m => m.Id == id)
                                       select student).Aggregate(intialize, (current, student) => current + (student.Code + ", "));

            if (itemsCannotIdentify != intialize)
            {
                message = string.Format(ConstantMessages.SomeItemsCanNotIdentify, itemsCannotIdentify.TrimEnd(','));
                return false;
            }

            var itemsInUse = (from student in students
                              let id = student.Id
                              where DataContex.GroupStudents.Any(m => m.IdStudent == id) || DataContex.StudentLecturers.Any(m => m.IdStudent == id) || DataContex.StudentMarks.Any(m => m.IdStudent == id)
                              select student).Aggregate(intialize, (current, student) => current + (student.Code + ", "));

            if (itemsInUse != intialize)
            {
                message = string.Format(ConstantMessages.SomeItemsInUseCanNotDelete, itemsInUse.TrimEnd(','));
                return false;
            }

            message = string.Empty;
            return true;
        }

        /// <summary>
        /// Delete object
        /// </summary>
        public void DeleteStudents(List<Student> students)
        {
            for (var i = students.Count - 1; i >= 0; i--)
            {
                var id = students[i].Id;
                var deleteStudent = DataContex.Students.Single(m => m.Id == id);

                // Delete Group Student
                var deleteGStudent = DataContex.GroupStudents.Where(m => m.IdStudent == id).ToList();
                for (var index = deleteGStudent.Count - 1; index >= 0; index--)
                {
                    var idGroupStudent = deleteGStudent[index].Id;
                    var deleteGroupStudent = DataContex.GroupStudents.Single(m => m.Id == idGroupStudent);
                    DataContex.GroupStudents.DeleteObject(deleteGroupStudent);
                }

                // Delete Student Mark
                var deleteMStudent = DataContex.StudentMarks.Where(m => m.IdStudent == id).ToList();
                for (var index = deleteMStudent.Count - 1; index >= 0; index--)
                {
                    var idStudentMark = deleteMStudent[index].Id;
                    var deleteGroupStudent = DataContex.StudentMarks.Single(m => m.Id == idStudentMark);
                    DataContex.StudentMarks.DeleteObject(deleteGroupStudent);
                }

                // Delete Student Graduation
                var deleteGrStudent = DataContex.StudentGraduations.Where(m => m.IdStudent == id).ToList();
                for (var index = deleteGrStudent.Count - 1; index >= 0; index--)
                {
                    var idStudentGraduation = deleteGrStudent[index].Id;
                    var deleteStudentGraduation = DataContex.StudentGraduations.Single(m => m.Id == idStudentGraduation);
                    DataContex.StudentGraduations.DeleteObject(deleteStudentGraduation);
                }

                // Delete Student Lecturer
                var deleteLStudent = DataContex.StudentLecturers.Where(m => m.IdStudent == id).ToList();
                for (var index = deleteLStudent.Count - 1; index >= 0; index--)
                {
                    var idStudentLecturer = deleteLStudent[index].Id;
                    var deleteStudentLecturer = DataContex.StudentLecturers.Single(m => m.Id == idStudentLecturer);
                    DataContex.StudentLecturers.DeleteObject(deleteStudentLecturer);
                }

                // DeleteSubCommittee Student
                var deleteSuStudent = DataContex.SubcommitteeStudents.Where(m => m.IdStudent == id).ToList();
                for (var index = deleteSuStudent.Count - 1; index >= 0; index--)
                {
                    var idSubcommitteeStudent = deleteSuStudent[index].Id;
                    var deleteSubcommitteeStudent = DataContex.SubcommitteeStudents.Single(m => m.Id == idSubcommitteeStudent);
                    DataContex.SubcommitteeStudents.DeleteObject(deleteSubcommitteeStudent);
                }

                // Delete Student
                DataContex.Students.DeleteObject(deleteStudent);
            }
            DataContex.SaveChanges();
        }

        public void DeleteOldStudent(int major, bool term)
        {
            var students = DataContex.Students.Where(s => s.IdMajor == major && s.Term == term).ToList();
            DeleteStudents(students);
        }
        #endregion      
    }
}